package com.ruoyi.web.utils;

import cn.hutool.core.util.ArrayUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.enums.AbnormalEnum;
import com.ruoyi.framework.web.exception.TadpoleException;
import com.ruoyi.web.enums.CommonDictEnum;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 初始化对象工具类
 *
 * @since 2022/8/14 15:58
 */
@Component
@AllArgsConstructor
public class CommonUtil {

    /**
     * id属性名
     */
    public static final String ID = "id";
    /**
     * 创建人名称属性名
     */
    public static final String CREATE_BY_NAME = "createByName";
    /**
     * 修改人名称属性名
     */
    public static final String UPDATE_BY_NAME = "updateByName";
    /**
     * 状态属性名
     */
    public static final String STATUS = "status";
    /**
     * 是否删除属性名
     */
    public static final String IS_DELETE = "isDeleted";

    private final IdWorker idWorker;
    private final ObjectMapper objectMapper;


    /**
     * 获得雪花id
     *
     * @return java.lang.Long
     * @author gong_da_kai
     * @since 2021/11/22
     */
    public Long getId() {
        return idWorker.nextId();
    }

    /**
     * 抛出异常，"操作失败"
     *
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public static void throwError() {
        throw new TadpoleException(AbnormalEnum.MSG.UNKNOWN);
    }

    /**
     * 获得分页开始下标
     *
     * @param pageNum  页码
     * @param pageSize 条数
     * @return {@link int}
     * @since 2022/8/26 19:25
     */
    public static int getStartIndex(int pageNum, int pageSize) {
        if (pageNum == 0) {
            pageNum = 1;
        }

        return (pageNum - 1) * pageSize;
    }

    /**
     * 获得分页结束下标
     *
     * @param pageNum  页码
     * @param pageSize 条数
     * @return {@link int}
     * @since 2022/10/10 17:03
     */
    public static int getEndIndex(int pageNum, int pageSize) {
        if (pageNum == 0) {
            pageNum = 1;
        }

        return pageNum * pageSize;
    }

    /**
     * 对象 -> json
     *
     * @param o 对象
     * @return {@link String}
     * @since 2022/8/26 20:54
     */
    public String toJson(Object o) {
        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * json -> 对象
     *
     * @param json json
     * @param type class
     * @return {@link T}
     * @since 2022/8/26 20:57
     */
    public <T> T parseJson(String json, Class<T> type) {
        try {
            return objectMapper.readValue(json, type);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取参数
     *
     * @param paramMap 参数集合
     * @param name     参数名称
     * @param remove   是否移除参数
     * @return {@link String}
     * @since 2022/11/12 17:28
     */
    public static String getParamString(Map<String, String[]> paramMap, String name, boolean remove) {
        String[] values = paramMap.get(name);
        if (ArrayUtil.isEmpty(values)) {
            return null;
        }

        if (remove) {
            paramMap.remove(name);
        }

        return values[0];
    }

    /**
     * 毫秒转化为LocalDateTime
     *
     * @param millis 毫秒
     * @return {@link LocalDateTime}
     * @since 2023/2/9 16:35
     */
    public static LocalDateTime millis2LocalDateTime(long millis) {
        Instant instant = Instant.ofEpochMilli(millis);
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * 获取当前用户
     *
     * @return {@link SysUser}
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public static SysUser getLoginUser() {
        return SecurityUtils.getLoginUser().getUser();
    }

    /**
     * 获取当前用户
     *
     * @return {@link SysUser}
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public static SysUser getLoginUserNotNull() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (Objects.isNull(user)) {
            throwError();
        }

        return user;
    }

    /**
     * 创建时初始化通用数据
     *
     * @param entity 实体
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initCreateAbout(BaseEntity entity) {
        initCreateAbout(entity, new Date(), getLoginUserNotNull());
    }

    /**
     * 创建时初始化通用数据
     *
     * @param entity 实体
     * @param date   时间
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initCreateAbout(BaseEntity entity, Date date) {
        initCreateAbout(entity, date, getLoginUserNotNull());
    }

    /**
     * 创建时初始化通用数据
     *
     * @param entity 实体
     * @param user   用户
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initCreateAbout(BaseEntity entity, SysUser user) {
        initCreateAbout(entity, new Date(), user);
    }

    /**
     * 创建时初始化通用数据
     *
     * @param entity 实体
     * @param date   时间
     * @param user   用户
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initCreateAbout(BaseEntity entity, Date date, SysUser user) {
        setId(entity);
        entity.setCreateBy(user.getUserId().toString());
        entity.setCreateTime(date);
        setUserName(entity, user, CommonUtil.CREATE_BY_NAME);
        setStatus(entity);
        setIsDeleted(entity);

        initUpdateAbout(entity, date, user);
    }

    /**
     * 修改时初始化通用数据
     *
     * @param entity 实体
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initUpdateAbout(BaseEntity entity) {
        initUpdateAbout(entity, new Date(), getLoginUser());
    }

    /**
     * 修改时初始化通用数据
     *
     * @param entity 实体
     * @param date   时间
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initUpdateAbout(BaseEntity entity, Date date) {
        initUpdateAbout(entity, date, getLoginUser());
    }

    /**
     * 修改时初始化通用数据
     *
     * @param entity 实体
     * @param user   用户
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initUpdateAbout(BaseEntity entity, SysUser user) {
        initUpdateAbout(entity, new Date(), user);
    }

    /**
     * 修改时初始化通用数据
     *
     * @param entity 实体
     * @param date   时间
     * @param user   用户
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void initUpdateAbout(BaseEntity entity, Date date, SysUser user) {
        entity.setUpdateBy(user.getUserId().toString());
        entity.setUpdateTime(date);
        setUserName(entity, user, CommonUtil.UPDATE_BY_NAME);
    }

    /**
     * 创建时，赋值id
     *
     * @param entity 实体类
     * @author gong_da_kai
     * @since 2021/11/20
     */
    public void setId(BaseEntity entity) {
        Method setter = ReflectUtil.getSetter(entity, ID, Long.class);

        try {
            if (setter == null) {
                return;
            }

            setter.invoke(entity, idWorker.nextId());
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }


    /**
     * 创建时设置创建人名称
     * <p>修改时设置修改人名称
     *
     * @param entity    实体类
     * @param user      用户
     * @param fieldName 属性名
     * @author gong_da_kai
     * @since 2021/11/20
     */
    private static void setUserName(BaseEntity entity, SysUser user, String fieldName) {
        Method setter = ReflectUtil.getSetter(entity, fieldName, String.class);

        try {
            if (setter == null) {
                return;
            }

            setter.invoke(entity, user.getUserName());
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建时，如果状态为空，设置状态为 0正常
     * {@link CommonDictEnum.Status}
     *
     * @param entity 实体类
     * @author gong_da_kai
     * @since 2021/11/20
     */
    private static void setStatus(BaseEntity entity) {
        Method getter = ReflectUtil.getGetter(entity, CommonUtil.STATUS);
        Method setter = ReflectUtil.getSetter(entity, CommonUtil.STATUS, String.class);

        try {
            // 判断这个类是否有status属性
            if (getter == null) {
                return;
            }

            // 状态没有值时才设置为默认值0
            Object val = getter.invoke(entity);
            if (val == null) {
                setter.invoke(entity, CommonDictEnum.Status.NORMAL.getValue());
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建时，设置是否删除为 0未删除
     * {@link CommonDictEnum.YesOrNo}
     *
     * @param entity 实体类
     * @author gong_da_kai
     * @since 2021/11/20
     */
    private static void setIsDeleted(BaseEntity entity) {
        Method setter = ReflectUtil.getSetter(entity, CommonUtil.IS_DELETE, String.class);

        try {
            if (setter == null) {
                return;
            }

            setter.invoke(entity, CommonDictEnum.YesOrNo.NO.getValue());
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
